package stark.app.function.paint;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.blankj.utilcode.util.ImageUtils;
import com.blankj.utilcode.util.PathUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.vilyever.drawingview.DrawingView;
import com.vilyever.drawingview.brush.drawing.CenterCircleBrush;
import com.vilyever.drawingview.brush.drawing.CircleBrush;
import com.vilyever.drawingview.brush.drawing.DrawingBrush;
import com.vilyever.drawingview.brush.drawing.EllipseBrush;
import com.vilyever.drawingview.brush.drawing.IsoscelesTriangleBrush;
import com.vilyever.drawingview.brush.drawing.LineBrush;
import com.vilyever.drawingview.brush.drawing.PenBrush;
import com.vilyever.drawingview.brush.drawing.PolygonBrush;
import com.vilyever.drawingview.brush.drawing.RectangleBrush;
import com.vilyever.drawingview.brush.drawing.RhombusBrush;
import com.vilyever.drawingview.brush.drawing.RightAngledTriangleBrush;
import com.vilyever.drawingview.brush.drawing.RoundedRectangleBrush;
import com.vilyever.drawingview.brush.drawing.ShapeBrush;
import com.vilyever.drawingview.brush.text.TextBrush;
import com.vilyever.drawingview.db.DrawRecord;
import com.vilyever.drawingview.db.DrawRecordDbUtil;
import com.vilyever.drawingview.model.DrawingStep;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import io.reactivex.rxjava3.core.ObservableEmitter;
import stark.app.R;
import stark.app.databinding.FragmentDrawingBinding;
import stark.common.basic.base.BaseNoModelFragment;
import stark.common.basic.utils.RxUtil;

/**
 * DrawingFragment
 * AndroidDrawingBoard <com.vilyever.androiddrawingboard>
 * Created by vilyever on 2015/9/21.
 * Feature:
 */
public class DrawingFragment extends BaseNoModelFragment<FragmentDrawingBinding> {
    public static final String KEY_DRAW_RECORD = "key_draw_record";

    private ThicknessAdjustController mThicknessAdjustController;
    private List<Button> mSingleSelectionButtons;

    private List<ShapeBrush> mShapeBrushes = new ArrayList<>();
    private PenBrush mPenBrush;
    private TextBrush mTextBrush;
    private DrawRecord mRecord;

    @Override
    protected int onCreate() {
        return R.layout.fragment_drawing;
    }

    @Override
    protected void initView() {
        Bundle bundle = getArguments();
        if (bundle != null && bundle.containsKey(KEY_DRAW_RECORD)) {
            mRecord = (DrawRecord) bundle.get(KEY_DRAW_RECORD);
        }
        mDataBinding.drawingView.setUndoRedoStateDelegate(new DrawingView.UndoRedoStateDelegate() {
            @Override
            public void onUndoRedoStateChange(DrawingView drawingView, boolean canUndo, boolean canRedo) {
                mDataBinding.btnUndo.setEnabled(canUndo);
                mDataBinding.btnRedo.setEnabled(canRedo);
            }
        });

        mDataBinding.drawingView.setInterceptTouchDelegate(new DrawingView.InterceptTouchDelegate() {
            @Override
            public void requireInterceptTouchEvent(DrawingView drawingView, boolean isIntercept) {

            }
        });

        mDataBinding.drawingView.setDrawingStepDelegate(new DrawingView.DrawingStepDelegate() {
            @Override
            public void onDrawingStepBegin(DrawingView drawingView, DrawingStep step) {
            }

            @Override
            public void onDrawingStepChange(DrawingView drawingView, DrawingStep step) {

            }

            @Override
            public void onDrawingStepEnd(DrawingView drawingView, DrawingStep step) {
            }

            @Override
            public void onDrawingStepCancel(DrawingView drawingView, DrawingStep step) {
            }
        });

        mDataBinding.drawingView.setBackgroundDatasource(new DrawingView.BackgroundDatasource() {
            @Override
            public Drawable gainBackground(DrawingView drawingView, String identifier) {
                return null;
            }
        });
        mDataBinding.btnSave.setOnClickListener(v -> {
            this.save();
        });
        mDataBinding.btnUndo.setEnabled(false);
        mDataBinding.btnUndo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDataBinding.drawingView.undo();
            }
        });

        mDataBinding.btnRedo.setEnabled(false);
        mDataBinding.btnRedo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDataBinding.drawingView.redo();
            }
        });

        mDataBinding.btnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDataBinding.drawingView.clear();
            }
        });

        mPenBrush = PenBrush.defaultBrush();
        mDataBinding.drawingView.setBrush(mPenBrush);
        mDataBinding.btnPen.setSelected(true);
        mDataBinding.btnPen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                selectButton(mSingleSelectionButtons, mDataBinding.btnPen);
                mDataBinding.drawingView.setBrush(mPenBrush);
            }
        });

        mShapeBrushes.add(PolygonBrush.defaultBrush());
        mShapeBrushes.add(LineBrush.defaultBrush());
        mShapeBrushes.add(RectangleBrush.defaultBrush());
        mShapeBrushes.add(RoundedRectangleBrush.defaultBrush());
        mShapeBrushes.add(CircleBrush.defaultBrush());
        mShapeBrushes.add(EllipseBrush.defaultBrush());
        mShapeBrushes.add(RightAngledTriangleBrush.defaultBrush());
        mShapeBrushes.add(IsoscelesTriangleBrush.defaultBrush());
        mShapeBrushes.add(RhombusBrush.defaultBrush());
        mShapeBrushes.add(CenterCircleBrush.defaultBrush());
        mDataBinding.btnShape.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DrawingBrush brush = null;

                if (!v.isSelected()) {
                    if (v.getTag() == null) {
                        v.setTag(1);
                    }
                    selectButton(mSingleSelectionButtons, (Button) v);
                } else {
                    int index = (int) v.getTag() + 1;
                    index = index % mShapeBrushes.size();
                    v.setTag(index);
                }

                brush = mShapeBrushes.get((Integer) v.getTag());
                mDataBinding.drawingView.setBrush(brush);
                String name = brush.getClass().getSimpleName();
                name = name.substring(0, name.length() - 5);
                ((Button) v).setText(name);
            }
        });

        mTextBrush = TextBrush.defaultBrush().setTypefaceStyle(Typeface.ITALIC);
        //设置自定义字体的话如下注释的示例所示
        //mTextBrush.setAssetFontPath("fonts/TestFont.ttf");
        mDataBinding.btnText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                selectButton(mSingleSelectionButtons, mDataBinding.btnText);
                mDataBinding.drawingView.setBrush(mTextBrush);
            }
        });

        mDataBinding.btnBgColor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Random random = new Random();
                int color = Color.argb(Math.abs(random.nextInt()) % 256, Math.abs(random.nextInt()) % 256, Math.abs(random.nextInt()) % 256, Math.abs(random.nextInt()) % 256);
                ((Button) v).setTextColor(color);
                mDataBinding.drawingView.setBackgroundColor(0, color);
            }
        });

        mDataBinding.btnThickness.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getThicknessAdjustController().setThickness((int) mPenBrush.getSize());
                getThicknessAdjustController().popupFromView(v, BasePopupController.PopupDirection.Left, true, 0, 0);
            }
        });

        mDataBinding.btnEraser.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.setSelected(!v.isSelected());
                mPenBrush.setIsEraser(v.isSelected());
                for (DrawingBrush brush : mShapeBrushes) {
                    brush.setIsEraser(v.isSelected());
                }
            }
        });

        mDataBinding.btnColor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Random random = new Random();
                int color = Color.argb(Math.abs(random.nextInt()) % 256, Math.abs(random.nextInt()) % 256, Math.abs(random.nextInt()) % 256, Math.abs(random.nextInt()) % 256);
                ((Button) v).setTextColor(color);

                mPenBrush.setColor(color);
                mTextBrush.setColor(color);
                for (DrawingBrush brush : mShapeBrushes) {
                    brush.setColor(color);
                }
            }
        });

        mDataBinding.btnFillType.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.setSelected(!v.isSelected());
                ShapeBrush.FillType fillType = v.isSelected() ? ShapeBrush.FillType.Solid : ShapeBrush.FillType.Hollow;
                mDataBinding.btnFillType.setText(fillType.name());
                for (ShapeBrush brush : mShapeBrushes) {
                    brush.setFillType(fillType);
                }
            }
        });

        mDataBinding.btnEdgeRounded.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.setSelected(!v.isSelected());
                for (ShapeBrush brush : mShapeBrushes) {
                    brush.setEdgeRounded(v.isSelected());
                }
            }
        });

        mDataBinding.btnOneStrokeOneLayer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.setSelected(!v.isSelected());
                mPenBrush.setOneStrokeToLayer(v.isSelected());
                mTextBrush.setOneStrokeToLayer(v.isSelected());
                for (DrawingBrush brush : mShapeBrushes) {
                    brush.setOneStrokeToLayer(v.isSelected());
                }
            }
        });

        mDataBinding.btnDeleteLayer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDataBinding.drawingView.deleteHandlingLayer();
            }
        });

        mSingleSelectionButtons = new ArrayList<>();
        mSingleSelectionButtons.add(mDataBinding.btnPen);
        mSingleSelectionButtons.add(mDataBinding.btnShape);
        mSingleSelectionButtons.add(mDataBinding.btnText);
    }

    @Override
    protected void initData() {
        if (mRecord != null) {
            mDataBinding.drawingView.refreshWithDrawingData(mRecord.getDrawingData());
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    /* #Accessors */
    public ThicknessAdjustController getThicknessAdjustController() {
        if (mThicknessAdjustController == null) {
            mThicknessAdjustController = new ThicknessAdjustController(getActivity());
            mThicknessAdjustController.setThicknessDelegate(new ThicknessAdjustController.ThicknessDelegate() {
                @Override
                public void thicknessDidChangeFromThicknessAdjustController(ThicknessAdjustController controller, int thickness) {
                    mPenBrush.setSize(thickness);
                    mTextBrush.setSize(thickness);
                    for (DrawingBrush brush : mShapeBrushes) {
                        brush.setSize(thickness);
                    }
                }
            });
        }
        return mThicknessAdjustController;
    }

    /* #Private Methods */
    private void selectButton(List<Button> buttons, Button button) {
        for (Button b : buttons) {
            b.setSelected(b == button);
        }
    }

    private void save() {
        showDialog("保存中...");
        RxUtil.create(new RxUtil.Callback<Boolean>() {
            @Override
            public void doBackground(ObservableEmitter<Boolean> emitter) {
                if (mRecord == null) {
                    addDrawRecord();
                } else {
                    updateDrawRecord(mRecord);
                }
                emitter.onNext(true);
            }

            @Override
            public void accept(Boolean ret) {
                dismissDialog();
                ToastUtils.showShort("已保存");
            }
        });
    }

    private void addDrawRecord() {
        DrawRecord record = new DrawRecord();
        record.name = System.currentTimeMillis() + "";
        String imgFilePath = PathUtils.getExternalAppFilesPath() + File.separator + record.name + ".png";
        Bitmap bitmap = ImageUtils.view2Bitmap(mDataBinding.drawingView);
        //这里不知为何通过jpeg的格式保存的时候，保存的图片是一全黑的图片
        ImageUtils.save(bitmap, imgFilePath, Bitmap.CompressFormat.PNG);
        record.setImgFilePath(imgFilePath);
        record.setDrawingData(mDataBinding.drawingView.getDrawingData());
        DrawRecordDbUtil.insert(record);
    }

    private void updateDrawRecord(DrawRecord record) {
        Bitmap bitmap = ImageUtils.view2Bitmap(mDataBinding.drawingView);
        //这里不知为何通过jpeg的格式保存的时候，保存的图片是一全黑的图片
        ImageUtils.save(bitmap, record.getImgFilePath(), Bitmap.CompressFormat.PNG);
        record.setDrawingData(mDataBinding.drawingView.getDrawingData());
        DrawRecordDbUtil.update(record);
    }
}